home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / comm / bbs / cit_src_AD08.lha / ctdl.c < prev    next >
C/C++ Source or Header  |  1998-06-06  |  56KB  |  2,280 lines

  1. /*
  2. *       ctdl.c
  3. *
  4. * Command-interpreter code for Citadel.
  5. */
  6. #define EXTERN
  7. #include "ctdl.h"
  8. #include "global_data.h"   /* all global data in one place */
  9. char QWKmain(void);
  10.  
  11. /* #define NEED_MSG_PEEKING */
  12. /* #define NEED_MSG_LIST */
  13. /*
  14. *       history
  15. *
  16. * 86Aug16 HAW  Kill history from file because of space problems.
  17. * 84May18 JLS/HAW Greeting modified for coherency.
  18. * 84Apr04 HAW  Upgrade to BDS 1.50a begun.
  19. * 83Mar08 CrT  Aide-special functions installed & tested...
  20. * 83Feb24 CrT/SB Menus rearranged.
  21. * 82Dec06 CrT  2.00 release.
  22. * 82Nov05 CrT  removed main() from room2.c and split into sub-fn()s
  23. */
  24. /*
  25. *       Contents
  26. *
  27. * doAide()    handles Aide-only       commands
  28. * doChat()    handles C(hat)    command
  29. * doEnter()   handles E(nter)   command
  30. * doForget()    handles Z(Forget room)  command
  31. * doGoto()    handles G(oto)    command
  32. * doHelp()    handles H(elp)    command
  33. * doKnown()   handles K(nown rooms)   command
  34. * doLogin()   handles L(ogin)   command
  35. * doLogout()    handles T(erminate)     command
  36. * doMeet()    handles M(eet) User command
  37. * doRead()    handles R(ead)    command
  38. * doRegular()   fanout for above commands
  39. * doSkip()    handles S(kip)    command
  40. * doSysop()   handles sysop-only      commands
  41. * doUngoto()    handles U(ngoto)  command
  42. * getCommand()    prints prompt and gets command char
  43. * greeting()    System-entry blurb etc
  44. * main()      has the central menu code
  45. */
  46. static char NoChatAtAll = FALSE;
  47. extern CONFIG     cfg;    /* The main variable to be saved      */
  48. extern aRoom      roomBuf;  /* Room buffer    */
  49. extern MessageBuffer    msgBuf; /* Message buffer   */
  50. extern MessageBuffer    tempMess; /* Message buffer   */
  51. extern logBuffer  logBuf; /* Person's log buffer    */
  52. extern logBuffer  logTmp; /* Person's log buffer    */
  53. extern rTable     *roomTab; /* Room index for RAM   */
  54. extern LogTable   *logTab;  /* Log  index for RAM   */
  55. extern struct floor *FloorTab;
  56. extern long       FDSectCount;  /* size of files in directory   */
  57. extern int    thisRoom; /* Current room   */
  58. extern SECTOR_ID  pulledMLoc; /* Loc of msg to be pulled    */
  59. extern MSG_NUMBER pulledMId;  /* Id of msg to be pulled   */
  60. extern char       *who_str;
  61. extern char       remoteSysop;
  62. extern char       onConsole;  /* Where IO is ...    */
  63. extern char       whichIO;  /* Where IO is ...    */
  64. extern char       outFlag;
  65. extern char       loggedIn; /* Are we logged in?    */
  66. extern char       echo;
  67. extern char       newCarrier; /* Just got carrier, hurrah!    */
  68. extern char       justLostCarrier;/* Boo, hiss!   */
  69. extern char       textDownload; /* flag   */
  70. extern char       haveCarrier;
  71. extern char       *baseRoom;
  72. extern char       heldMess;
  73. extern char       anyEcho;
  74. extern char       PrintBanner;
  75. /*
  76. * doAide()
  77. *
  78. * This function handles the aide-only menu.
  79. *
  80. * return FALSE to fall invisibly into default error msg.
  81. */
  82. char doAide(char moreYet, char first)
  83.   {
  84.   label oldName;
  85.   int  rm;
  86.   char chatStack;
  87.   char fname[100];
  88.   char *ValAide[] =
  89.     {
  90.     "Chat           ", "Delete empty rooms  ", "Edit room\n",
  91.     "Insert message ", "Kill room           ", "S\bNot available.\n",
  92.     "\b", " ", ""
  93.  
  94.     };
  95.   extern char *APrivateRoom;
  96.   extern SListBase Moderators;
  97.   if (roomBuf.rbflags.ISDIR == 1 && HalfSysop())
  98.   ExtraOption(ValAide, "Add File\n");
  99.   if (!aide)
  100.     {
  101.     PushBack('E');
  102.  
  103.     }
  104.   if (moreYet)   first = '\0';
  105.   if (first)     PushBack(first);
  106.  
  107.     SpecialMessage("Status:Aide Functions");
  108.  
  109.   RegisterThisMenu("aide.mnu", ValAide);
  110.   switch (GetMenuChar())
  111.     {
  112.     case 'A':
  113.     getString("EFILEN", fname, sizeof fname, 0);
  114.     if (access(fname, 0) != 0)
  115.       {
  116.       Output_Citadel_Message("NOSUCH",(long)fname,NULL,NULL);   /* no such file */
  117.       break;
  118.  
  119.       };
  120.     if (CopyFile(fname, &roomBuf))
  121.       {
  122.       FileCommentUpdate(fname, FALSE);
  123.  
  124.       };
  125.     break;
  126.     case '\b':
  127.     mPrintf("\b \b"); /* not sure why this is necessary */
  128.     return BACKED_OUT;
  129.     case 'C':
  130.     logMessage(TRIED_CHAT, "", 'C');
  131.     if (NoChatAtAll && !SomeSysop())
  132.       {
  133.       if (!MultiBanner("nochat"))
  134.       tutorial("nochat.blb", TRUE);
  135.  
  136.       }
  137.     else
  138.       {
  139.       chatStack = cfg.BoolFlags.noChat;
  140.       cfg.BoolFlags.noChat = FALSE;
  141.       if (whichIO == MODEM) ringSysop();
  142.       else      interact(TRUE) ;
  143.       cfg.BoolFlags.noChat = chatStack;
  144.  
  145.       }
  146.     break;
  147.     case 'D':
  148.     ZeroMsgBuffer(&msgBuf);
  149.     sPrintf(msgBuf.mbtext, "The following empty rooms deleted by %s: ",
  150.     logBuf.lbname);
  151.     if (!getYesNo("CONFRM"))
  152.     break;
  153.     strCpy(oldName, roomBuf.rbname);
  154.     indexRooms();
  155.     if ((rm=roomExists(oldName)) != ERROR)  getRoom(rm);
  156.     else          getRoom(LOBBY);
  157.     aideMessage(NULL, /* noteDeletedMessage== */ FALSE );
  158.     break;
  159.     case 'E':
  160.     renameRoom();
  161.     break;
  162.     case 'I':
  163.     ZeroMsgBuffer(&msgBuf);
  164.     if (
  165.     thisRoom   == AIDEROOM
  166.     ||
  167.     pulledMId  == 0l
  168.     )
  169.       {
  170.       Output_Citadel_Message("NOMSGI",NULL,NULL,NULL); /* no message insertable*/
  171.       break;
  172.  
  173.       }
  174.     if (!getYesNo("CONFRM"))
  175.     break;
  176.     noteAMessage(roomBuf.msg, MSGSPERRM, pulledMId, pulledMLoc);
  177.     putRoom(thisRoom);
  178.     noteRoom();
  179.     sPrintf(msgBuf.mbtext,"Following message inserted in %s> by %s",
  180.     formRoom(thisRoom, FALSE, FALSE), logBuf.lbname);
  181.     aideMessage(NULL, /* noteDeletedMessage == */ TRUE);
  182.     break;
  183.     case 'K':
  184.     if (
  185.     thisRoom == LOBBY
  186.     ||
  187.     thisRoom == MAILROOM
  188.     ||
  189.     thisRoom == AIDEROOM
  190.     )
  191.       {
  192.       Output_Citadel_Message("NOKILL",NULL,NULL,NULL);
  193.       break;
  194.  
  195.       }
  196.     if (!getYesNo("CONFRM"))   break;
  197.     ZeroMsgBuffer(&msgBuf);
  198.     sPrintf( msgBuf.mbtext, "%s> killed by %s",roomBuf.rbname,logBuf.lbname);
  199.     aideMessage(NULL, /* noteDeletedMessage == */ FALSE);
  200.     KillInfo(roomBuf.rbname);
  201.     roomBuf.rbflags.INUSE = FALSE;
  202.     putRoom(thisRoom);
  203.     noteRoom();
  204.     getRoom(LOBBY);
  205.     break;
  206.     case 'S':
  207.     #ifdef NEED_AVAILABLE
  208.     changeDate();
  209.     #endif
  210.     break;
  211.  
  212.     }
  213.   return GOOD_SELECT;
  214.  
  215.   }
  216. /*
  217. * doChat()
  218. *
  219. * Chatting!
  220. */
  221. char doChat(char moreYet, char first)
  222.   {
  223.   if (moreYet)   first = '\0';
  224.   if (first)     oChar(first);
  225.   if (whichIO != MODEM)
  226.     {
  227.     interact(TRUE) ;
  228.     if (whichIO == CONSOLE)
  229.     if (getYesNo("MODEMM"))
  230.       {
  231.       whichIO = MODEM;
  232.       setUp(FALSE);
  233.       if (!gotCarrier()) EnableModem(FALSE);
  234.  
  235.       }
  236.  
  237.     }
  238.   else
  239.     {
  240.     logMessage(TRIED_CHAT, "", 'C');
  241.     if (cfg.BoolFlags.noChat)
  242.       {
  243.       if (!MultiBanner("nochat"))
  244.       tutorial("nochat.blb", TRUE);
  245.       return GOOD_SELECT;
  246.  
  247.       }
  248.     ringSysop();
  249.  
  250.     }
  251.   return GOOD_SELECT;
  252.  
  253.   }
  254. /*
  255. * doEnter()
  256. *
  257. * This function handles the E(nter) command.
  258. */
  259. char doEnter(char moreYet, char first)
  260.   {
  261.   #define CONFIGURATION   0
  262.   #define MESSAGE   1
  263.   #define PASSWORD  2
  264.   #define ROOM    3
  265.   #define ENTERFILE       4
  266.   #define CONTINUED       5
  267.   #define NETWORK   6
  268.   #define DEFAULT_MESSAGE 7
  269.   char what;      /* one of above seven */
  270.   SListBase  ESelects =
  271.     {
  272.     NULL, FindSelect, NULL, NoFree, NULL
  273.  
  274.     };
  275.   char *EnterOpts[] =
  276.     {
  277.     TERM "\r", TERM "\n", NTERM "Xmodem", NTERM "Ymodem",
  278.     #ifdef WXMODEM_AVAILABLE
  279.     NTERM "Wxmodem",
  280.     #endif
  281.     TERM "Configuration", TERM "Message", TERM "Password",
  282.     TERM "Room", TERM "Held Message", TERM "Net-Message",
  283.     /* These are for external protocols -- don't delete them! */
  284.     " ", " ", " ",
  285.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", ""
  286.  
  287.     };
  288.   char abort, Protocol, again;
  289.   char *letter, cmdbuf[30];
  290.   if (loggedIn && roomBuf.rbflags.ISDIR == 1)
  291.   ExtraOption(EnterOpts, TERM "F");
  292.   AddExternProtocolOptions(EnterOpts, TRUE);
  293.   if (moreYet)   first = '\0';
  294.   abort       = FALSE  ;
  295.   if (thisRoom != MAILROOM && !loggedIn &&
  296.   !cfg.BoolFlags.unlogEnterOk)
  297.     {
  298.     Output_Citadel_Message("ENTERM",NULL,NULL,NULL);
  299.     return GOOD_SELECT;
  300.  
  301.     }
  302.   SpecialMessage("Status:Enter");
  303.   if (first)     PushBack(first);
  304.   do
  305.     {
  306.     again = FALSE;
  307.     outFlag = OUTOK;
  308.     Protocol  = ASCII  ;
  309.     what  = DEFAULT_MESSAGE;
  310.     if (CmdMenuList(EnterOpts, &ESelects, "entopt.mnu", cmdbuf,
  311.     moreYet, TRUE) == BACKED_OUT)
  312.     return BACKED_OUT;
  313.     letter = cmdbuf;
  314.     do
  315.       {
  316.       switch (*letter)
  317.         {
  318.         case '\r':
  319.         case '\n':
  320.         break;
  321.         #ifdef WXMODEM_AVAILABLE
  322.         case 'X':
  323.         case 'Y':
  324.         case 'W':
  325.         Protocol = (*letter == 'Y') ? YMDM : (*letter == 'X') ? XMDM : WXMDM;
  326.         break;
  327.         #else
  328.         case 'X':
  329.         case 'Y':
  330.         Protocol = (*letter == 'Y') ? YMDM : XMDM;
  331.         break;
  332.         #endif
  333.         case 'F':
  334.         if (Protocol == ASCII)
  335.           {
  336.           mPrintf("\b\bXmodem F ");
  337.           Protocol = XMDM;
  338.  
  339.           }
  340.         mPrintf("\bile Upload ");
  341.         if (!roomBuf.rbflags.UPLOAD || logBuf.lbflags.TWIT)
  342.           {
  343.           Output_Citadel_Message("NOUPLD",NULL,NULL,NULL);
  344.           abort = TRUE;
  345.  
  346.           }
  347.         what    = ENTERFILE;
  348.         break;
  349.         case 'C':
  350.         again = reconfigure();
  351.         what  = CONFIGURATION;
  352.         break;
  353.         case 'M':
  354.         what  = MESSAGE;
  355.         break;
  356.         case 'P':
  357.         what  = PASSWORD     ;
  358.         break;
  359.         case 'R':
  360.         if (!cfg.BoolFlags.nonAideRoomOk && !aide)
  361.           {
  362.           Output_Citadel_Message("NOTAID",NULL,NULL,NULL);
  363.           abort   = TRUE;
  364.           break;
  365.  
  366.           }
  367.         if (!loggedIn)
  368.           {
  369.           Output_Citadel_Message("LGICRR",NULL,NULL,NULL);
  370.           abort = TRUE;
  371.           break;
  372.  
  373.           }
  374.         if (logBuf.lbflags.TWIT)
  375.           {
  376.           Output_Citadel_Message("TWITNR",NULL,NULL,NULL);
  377.           abort = TRUE;
  378.           break;
  379.  
  380.           }
  381.         what  = ROOM;
  382.         break;
  383.         case 'H':
  384.         what = CONTINUED;
  385.         Protocol   = ASCII; /* can't do this using protocol */
  386.         break;
  387.         case 'N':
  388.         if( logBuf.lbflags.NET_PRIVS )
  389.           what = NETWORK;
  390.         else Output_Citadel_Message("NONETP",NULL, NULL, NULL);
  391.         break;
  392.         default:
  393.         if ((Protocol = FindProtocolCode(*letter, TRUE)) == -1)
  394.         abort = TRUE;
  395.  
  396.         }
  397.       ++letter;
  398.  
  399.       }
  400.     while (moreYet && !abort && *letter);
  401.  
  402.     }
  403.   while (again);
  404.   KillList(&ESelects);
  405.   doCR();
  406.   if (!abort)
  407.     {
  408.     if (whichIO != CONSOLE && loggedIn &&
  409.     (thisRoom == MAILROOM || roomTab[thisRoom].rtflags.ANON))
  410.     echo = CALLER;
  411.     switch (what)
  412.       {
  413.       case DEFAULT_MESSAGE:
  414.       if (Protocol != ASCII)
  415.         {
  416.         Output_Citadel_Message("MSGTRN",NULL,NULL,NULL);
  417.         }
  418.       case   MESSAGE:   makeMessage(Protocol);  break;
  419.       case  PASSWORD:   newPW()   ; break;
  420.       case      ROOM:   makeRoom()    ; break;
  421.       case ENTERFILE:   upLoad(Protocol,NULL,TRUE)  ; break;
  422.       case CONTINUED:   hldMessage(FALSE) ; break;
  423.       case   NETWORK:   netMessage(Protocol); break;
  424.  
  425.       }
  426.     echo = BOTH;
  427.  
  428.     }
  429.   return GOOD_SELECT ;
  430.  
  431.   }
  432. /*
  433. * doForget()
  434. *
  435. * This function handles the (Forget room) command.
  436. */
  437. char doForget(char expand)
  438.   {
  439.   if (!expand)
  440.     {
  441.     mPrintf("%s\n ", roomBuf.rbname);
  442.     if (thisRoom == LOBBY    ||
  443.     thisRoom == MAILROOM ||
  444.     thisRoom == AIDEROOM)
  445.       {
  446.       Output_Citadel_Message("CANTFG",NULL,NULL,NULL);
  447.       return GOOD_SELECT ;
  448.  
  449.       }
  450.     if (!getYesNo("CONFRM"))   return GOOD_SELECT;
  451.     SetKnown(FORGET_OFFSET, 0, thisRoom, &logBuf);
  452.     gotoRoom(baseRoom, 'S');
  453.  
  454.     }
  455.   else
  456.     {
  457.     /* mPrintf("\b\b "); */
  458.     listRooms(FORGOTTEN);
  459.  
  460.     }
  461.   return GOOD_SELECT;
  462.  
  463.   }
  464. /*
  465. * doGoto()
  466. *
  467. * This function handles the G(oto) command.
  468. */
  469. char doGoto(char expand)
  470.   {
  471.   label roomName;
  472.   int   oldRoom;
  473.   outFlag = IMPERVIOUS;
  474.   if (!expand)
  475.     {
  476.     oldRoom = thisRoom;
  477.     gotoRoom("", 'R');
  478.     if (oldRoom == thisRoom && loggedIn && !expert)
  479.     Output_Citadel_Message("NOMMSG",NULL,NULL,NULL);
  480.     return GOOD_SELECT;
  481.  
  482.     }
  483.   if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  484.     {
  485.     return BACKED_OUT;
  486.  
  487.     }
  488.   if (roomName[0] == '?')
  489.     {
  490.     listRooms(NOT_INTRO);
  491.  
  492.     }
  493.   else
  494.   gotoRoom(roomName, 'R');
  495.   return GOOD_SELECT;
  496.  
  497.   }
  498. /*
  499. * doHelp()
  500. *
  501. * This function the handles the H(elp) command.
  502. */
  503. char doHelp(char expand)
  504.   {
  505.   label fileName;
  506.  
  507.   SpecialMessage("Status:Help");
  508.  
  509.   if (!expand)
  510.     {
  511.     mPrintf("\n\n");
  512.     printHelp("mainhelp.hlp");
  513.     return GOOD_SELECT;
  514.  
  515.     }
  516.   if (getNormStr("", fileName, (sizeof fileName) - 4, BS_VALID) == BACKED_OUT)
  517.   return BACKED_OUT;
  518.   if (strLen(fileName) == 0)
  519.   strCpy(fileName, "mainhelp");
  520.   if (fileName[0] == '?')     printHelp("helpopt.hlp");
  521.   else
  522.     {
  523.     /* adding the extention makes things look simpler for   */
  524.     /* the user... and restricts the files which can be read  */
  525.     strCat(fileName, ".hlp");
  526.     printHelp(fileName);
  527.  
  528.     }
  529.   return GOOD_SELECT;
  530.  
  531.   }
  532. /*
  533. * doKnown()
  534. *
  535. * This function handles the K(nown rooms) command.
  536. */
  537. char doKnown(char expand)
  538.   {
  539.   char select = ERROR, c[2], again;
  540.   label matchstr;
  541.   char *KMenuOpts[] =
  542.     {
  543.     TERM "Anonymous rooms\n", TERM "Match", TERM "Directory rooms\n",
  544.     TERM "Shared rooms\n", TERM "Private rooms\n",
  545.     TERM "Z\bForgotten rooms\n", TERM "Information", TERM "Read-only\n",
  546.     TERM "C\bArchived rooms\n", TERM "\r", TERM "\n", ""
  547.  
  548.     };
  549.   SListBase  KSelects =
  550.     {
  551.     NULL, FindSelect, NULL, NoFree, NULL
  552.  
  553.     };
  554.  
  555.   SpecialMessage("Status:Known");
  556.  
  557.   if (!expand)
  558.     {
  559.     mPrintf("\n ");
  560.     listRooms(NOT_INTRO);
  561.  
  562.     }
  563.   else
  564.     {
  565.     do
  566.       {
  567.       again = FALSE;
  568.       if (CmdMenuList(KMenuOpts, &KSelects, "known.mnu", c, TRUE, TRUE)
  569.       == BACKED_OUT)
  570.       return BACKED_OUT;
  571.       switch (c[0])
  572.         {
  573.         case 'I':
  574.         AllInfo();
  575.         break;
  576.         case 'M':
  577.         if (getNormStr("",matchstr,NAMESIZE, BS_VALID) == BACKED_OUT)
  578.           {
  579.           again = TRUE;
  580.           select = ERROR;
  581.           PushBack('\b');
  582.           oChar(' ');
  583.  
  584.           }
  585.         else select = MATCH_SEL;
  586.         break;
  587.         case 'A':   select = ANON_SEL;      break;
  588.         case 'D':   select = DR_SEL;        break;
  589.         case 'S':   select = SH_SEL;        break;
  590.         case 'P':   select = PR_SEL;        break;
  591.         case 'Z':   select = FORGOTTEN;     break;
  592.         case 'C':   select = ARCH_SEL;      break;
  593.         case 'R':   select = READONLY;      break;
  594.         case '\r':
  595.         doCR();
  596.         case '\n':
  597.         strCpy(matchstr, "");
  598.         select = MATCH_SEL;
  599.         break;
  600.  
  601.         }
  602.       if (select != MATCH_SEL && select != ERROR)
  603.       listRooms(select);
  604.       else if (select != ERROR)
  605.       searchRooms(matchstr);
  606.  
  607.       }
  608.     while (again);
  609.  
  610.     }
  611.   KillList(&KSelects);
  612.   return GOOD_SELECT;
  613.  
  614.   }
  615. /*
  616. * doLogin()
  617. *
  618. * This function handles the L(ogin) command.
  619. */
  620. char doLogin(char moreYet)
  621.   {
  622.   label passWord;
  623.   if (!moreYet)   mPrintf("\n");
  624.  
  625.   SpecialMessage("Status:Login");
  626.  
  627.   if (loggedIn)
  628.     {
  629.     Output_Citadel_Message("ALRULG",NULL,NULL,NULL);
  630.     return GOOD_SELECT;
  631.  
  632.     }
  633.   echo  = CALLER;
  634.   if (getNormStr(moreYet ? "" : "ULGPWD",
  635.   passWord, NAMESIZE, (moreYet) ? BS_VALID : NO_ECHO) ==
  636.   BACKED_OUT)
  637.     {
  638.     return BACKED_OUT;
  639.  
  640.     }
  641.   echo  = BOTH;
  642.   login(passWord);
  643.   return GOOD_SELECT;
  644.  
  645.   }
  646. /*
  647. * doLogout()
  648. *
  649. * This function handles the T(erminate) command.
  650. */
  651. char doLogout(char expand, char first)
  652.   {
  653.   char cx;
  654.  
  655.   SpecialMessage("Status:Terminating");
  656.  
  657.   if (expand)   first = '\0';
  658.   outFlag = IMPERVIOUS;
  659.   if (heldMess && !cfg.BoolFlags.HoldOnLost)
  660.     {
  661.     Output_Citadel_Message("HOLDMS",NULL,NULL,NULL);
  662.     mAbort(); /* clear any first-run input fromuser */
  663.  
  664.     }
  665.   if (first)   oChar(first);
  666.   if( first )
  667.     {
  668.     cx = first;
  669.  
  670.     }
  671.   else cx = iChar();
  672.   switch (toUpper( cx ))
  673.     {
  674.     case '\b':
  675.     if (expand) return BACKED_OUT;
  676.     default:
  677.     Output_Citadel_Message("LGOPTS",NULL,NULL,NULL);
  678.     break;
  679.     case 'Q':
  680.     mPrintf("uit-also\n ");
  681.     if (!expand)
  682.       {
  683.       if (!getYesNo("CONFRM"))   break;
  684.  
  685.       }
  686.     if (!onLine()) break;
  687.     terminate( /* hangUp == */ TRUE, TRUE);
  688.     break;
  689.     case 'S':
  690.     mPrintf("tay\n ");
  691.     terminate( /* hangUp == */ FALSE, TRUE);
  692.     break;
  693.     case 'A':
  694.     mPrintf("bort\n ");
  695.     terminate( /* hangUp == */ TRUE, FALSE);
  696.  
  697.     }
  698.   outFlag = OUTOK;
  699.   return GOOD_SELECT;
  700.  
  701.   }
  702. OptValues Opt;
  703. char revOrder;  /* Udderly HIDEOUS kludge.  MOOOOOO! */
  704. char PhraseUser;
  705. /*
  706. * doMeet()
  707. *
  708. * This function handles the M(eet) User command.
  709. */
  710. char doMeet(char moreYet)
  711.   {
  712.   label User;
  713.   int   logNo;
  714.  
  715.     SpecialMessage("Status:Meet Users");
  716.  
  717.   if (!moreYet) doCR();
  718.   if (getNormStr(moreYet ? "" : "USMEET",
  719.   User, NAMESIZE, QUEST_SPECIAL | BS_VALID) == BACKED_OUT)
  720.     {
  721.     return BACKED_OUT;
  722.  
  723.     }
  724.   if (strLen(User) != 0)
  725.     {
  726.     if (User[0] == '?')
  727.       {
  728.       BioDirectory();
  729.       return GOOD_SELECT;
  730.  
  731.       }
  732.     logNo = findPerson(User, &logTmp);
  733.     if (logNo == ERROR)
  734.       {
  735.       Output_Citadel_Message("NOPERS",(long)User,NULL,NULL);
  736.       }
  737.     else
  738.       {
  739.       if (GetBioInfo(logNo))
  740.         {
  741.         Output_Citadel_Message("BIOOFU",(long)logTmp.lbname,NULL,NULL);
  742.         doCR();
  743.         mPrintf("%s\n ", msgBuf.mbtext);
  744.  
  745.         }
  746.       else  Output_Citadel_Message("NOBIOU",(long)logTmp.lbname,NULL,NULL);
  747.       }
  748.  
  749.     }
  750.   return GOOD_SELECT;
  751.  
  752.   }
  753. /*
  754. * doRead()
  755. *
  756. * This function handles the R(ead) command.
  757. */
  758. static void *FindUser(char *element, int x);
  759. int   UserOptAdd(char *str);
  760. char doRead(char moreYet, char first)
  761.   {
  762.   char abort = FALSE,
  763.   Compressed = FALSE,
  764.   extDir,
  765.   doDir,
  766.   again,
  767.   hostFile,
  768.   whichMess,
  769.   status = FALSE,
  770.   SrchUser,
  771.   srchPhrase,
  772.   protocol,
  773.   global,
  774.   filestuff = FALSE,
  775.   ReadArchive;
  776.   char *letter, secondletter;
  777.   char fileName[100];
  778.   int    CurRoom;
  779.   extern FILE* upfd;
  780.   SListBase  RSelects =
  781.     {
  782.     NULL, FindSelect, NULL, NoFree, NULL
  783.  
  784.     };
  785.   SListBase  CSelects =
  786.     {
  787.     NULL, FindSelect, NULL, NoFree, NULL
  788.  
  789.     };
  790.   extern char journalMessage, FormatFlag;
  791.   extern int outPut;
  792.   char *ReadOpts[] =
  793.     {
  794.     TERM "\r", TERM "\n",
  795.     #ifdef NO_DeARC_SUPPORT
  796.     TERM "Archive-Directory(s)\n",
  797.     #else
  798.     TERM "Archive",
  799.     #endif
  800.     TERM "Forward", NTERM "Global", NTERM "Local-only", TERM "New",
  801.     TERM "Old-reverse", TERM "Reverse", TERM "Status\n", NTERM "Xmodem",
  802.     #ifdef WXMODEM_AVAILABLE
  803.     NTERM "Wxmodem",
  804.     #endif
  805.     NTERM "Ymodem", NTERM "User", NTERM "Phrase",
  806.     /* these two are here rather than optional due to .RGE/.RGD */
  807.     TERM "Directory", TERM "Extended-Directory", " ", " ", " ", " ",
  808.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  809.     " ", " ", " ", " ", " ", ""
  810.  
  811.     };
  812.   #ifndef NO_DeARC_SUPPORT
  813.   char *CompOpts[] =
  814.     {
  815.     TERM "Directory(s)\n", TERM "File(s)\n", TERM "T\bFile(s)\n",
  816.     TERM "B\bFile(s)\n", TERM "\nDirectory(s)", ""
  817.  
  818.     };
  819.   #endif
  820.   char  cmdbuf[40];
  821.   whichMess = NEWoNLY;
  822.   if (moreYet)   first = '\0';
  823.   zero_struct(Opt);
  824.   Opt.Date = -1l;
  825.   InitListValues(&Opt.Users, FindUser, NULL, free, NULL);
  826.   if (thisRoom == MAILROOM && !loggedIn  &&
  827.   !cfg.BoolFlags.unlogReadOk)
  828.     {
  829.     showMessages(whichMess, revOrder,
  830.     logBuf.lbvisit[logBuf.lbgen[thisRoom] & CALLMASK],
  831.     OptionValidate);
  832.     return GOOD_SELECT;
  833.  
  834.     }
  835.   if (!loggedIn  &&  !cfg.BoolFlags.unlogReadOk)
  836.     {
  837.     Output_Citadel_Message("READMM",NULL,NULL,NULL);
  838.     return GOOD_SELECT;
  839.  
  840.     }
  841.   if (first)     PushBack(first);
  842.   if (roomBuf.rbflags.ISDIR == 1 && loggedIn && !logBuf.lbflags.TWIT)
  843.     {
  844.     ExtraOption(ReadOpts, TERM "Binary file(s)");
  845.     ExtraOption(ReadOpts, TERM "Textfile(s)");
  846.  
  847.     }
  848.   if (AnyCompression())
  849.   ExtraOption(ReadOpts, NTERM "Compressed");
  850.   AddExternProtocolOptions(ReadOpts, FALSE);
  851.   if (HalfSysop())
  852.   ExtraOption(ReadOpts, TERM "Invited-users");
  853.  
  854.   SpecialMessage("Status:Reading");
  855.  
  856.   do
  857.     {
  858.     again = FALSE;
  859.     protocol = ASCII;
  860.     whichMess = NEWoNLY;
  861.     extDir = doDir = hostFile = SrchUser = srchPhrase =
  862.     global = ReadArchive = PhraseUser = revOrder = FALSE;
  863.     if (CmdMenuList(ReadOpts, &RSelects, "readopt.mnu", cmdbuf, moreYet, TRUE) ==
  864.     BACKED_OUT)
  865.     return BACKED_OUT;
  866.     letter = cmdbuf;
  867.     do
  868.       {
  869.       outFlag = OUTOK;
  870.       switch (*letter)
  871.         {
  872.         case '\r':
  873.         doCR();
  874.         case '\n':
  875.         break;
  876.         case 'C':
  877.         Compressed = TRUE;
  878.         break;
  879.         case 'A':
  880.         if (   ( global || roomBuf.rbflags.ISDIR )
  881.             && ( logBuf.lbflags.DL_PRIVS || aide ) )
  882.           {
  883.           if (roomBuf.rbflags.DOWNLOAD || HalfSysop())
  884.             {
  885.             if (CmdMenuList(CompOpts, &CSelects, "", cmdbuf, TRUE,
  886.             FALSE) == BACKED_OUT)
  887.               {
  888.               again = TRUE;
  889.               PushBack('\b');
  890.  
  891.               }
  892.             else
  893.               {
  894.               switch (cmdbuf[0])
  895.                 {
  896.                 case '\n':
  897.                 case '\r':
  898.                 case 'D':
  899.                 ReadArchive = 1;
  900.                 break;
  901.                 case 'T':
  902.                 case 'B':
  903.                 case 'F':
  904.                 ReadArchive = 2;
  905.                 break;
  906.                 default:
  907.                 abort = TRUE;
  908.  
  909.                 }
  910.               break;
  911.  
  912.               }
  913.  
  914.             }
  915.           else
  916.             {
  917.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  918.             abort = TRUE;
  919.             break;
  920.  
  921.             }
  922.  
  923.           }
  924.         else
  925.           {
  926.           Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  927.           abort = TRUE;
  928.           break;
  929.           };
  930.  
  931.         break;
  932.         case 'F':
  933.         revOrder    = FALSE;
  934.         whichMess   = OLDaNDnEW;
  935.         goto commondate;
  936.         case 'G':
  937.         global  = TRUE;
  938.         break;
  939.         case 'L':
  940.         Opt.LocalOnly = TRUE;
  941.         break;
  942.         case 'N':
  943.         whichMess   = NEWoNLY;
  944.         goto commondate;
  945.         case 'O':
  946.         revOrder    = TRUE;
  947.         whichMess   = OLDoNLY;
  948.         goto commondate;
  949.         case 'R':
  950.         revOrder    = TRUE;
  951.         whichMess   = OLDaNDnEW;
  952.         commondate:
  953.         if (moreYet)
  954.           {
  955.           if (getString("", fileName, NAMESIZE,
  956.           BS_VALID | QUEST_SPECIAL) == BACKED_OUT)
  957.             {
  958.             again = TRUE;
  959.             oChar(' ');
  960.             PushBack('\b');
  961.             break;
  962.  
  963.             }
  964.           if (fileName[0] == '?')
  965.             {
  966.             tutorial("readdate.blb", TRUE);
  967.             KillList(&RSelects);
  968.             return GOOD_SELECT;
  969.  
  970.             }
  971.           if (strLen(fileName) != 0)
  972.           if (ReadDate(fileName, &Opt.Date) == ERROR)
  973.             {
  974.             Output_Citadel_Message("INVLDD",NULL,NULL,NULL);
  975.             KillList(&RSelects);
  976.             return GOOD_SELECT;
  977.  
  978.             }
  979.  
  980.           }
  981.         else
  982.           {
  983.           doCR();
  984.  
  985.           }
  986.         break;
  987.         case 'S':
  988.         status      = TRUE;
  989.         break;
  990.         #ifdef WXMODEM_AVAILABLE
  991.         case 'X':
  992.         case 'W':
  993.         case 'Y':
  994.         protocol    = (*letter == 'W') ? WXMDM :
  995.         (*letter == 'X') ? XMDM : YMDM;
  996.         break;
  997.         #else
  998.         case 'X':
  999.         case 'Y':
  1000.         protocol    = (*letter == 'X') ? XMDM : YMDM;
  1001.         break;
  1002.         #endif
  1003.         case 'B':
  1004.         case 'T':
  1005.         filestuff = TRUE;
  1006.         case 'E':
  1007.         case 'D':
  1008.         if (!logBuf.lbflags.DL_PRIVS && !aide)
  1009.           {
  1010.           Output_Citadel_Message("NODLDP",NULL,NULL,NULL);
  1011.           abort = TRUE;
  1012.           break;
  1013.  
  1014.           }
  1015.         if (filestuff)
  1016.           {
  1017.           if (roomBuf.rbflags.DOWNLOAD == 1 || TheSysop() ||
  1018.           remoteSysop)
  1019.             {
  1020.             hostFile      = TRUE ;
  1021.             textDownload    = (*letter == 'T') ? TRUE : FALSE;
  1022.             if (textDownload && protocol == ASCII)
  1023.               {
  1024.               char cx;
  1025.               cx = modIn();
  1026.               switch (secondletter = toUpper(cx))
  1027.                 {
  1028.                 case '\b':
  1029.                 again = TRUE;
  1030.                 PushBack('\b');
  1031.                 break;
  1032.                 case 'F':
  1033.                 mPrintf("Formatted");
  1034.                 FormatFlag = TRUE;
  1035.                 break;
  1036.                 default:
  1037.                 PushBack(secondletter);
  1038.                 case '\r':
  1039.                 case '\n':
  1040.                 case ' ':
  1041.                 doCR();
  1042.  
  1043.                 }
  1044.  
  1045.               }
  1046.  
  1047.             }
  1048.           else
  1049.             {
  1050.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1051.             abort = TRUE;
  1052.  
  1053.             }
  1054.  
  1055.           }
  1056.         else
  1057.           {
  1058.           if (roomBuf.rbflags.ISDIR == 1 || global)
  1059.             {
  1060.             if (global || roomBuf.rbflags.DOWNLOAD || TheSysop()
  1061.             || remoteSysop)
  1062.               {
  1063.               if (getNormStr("", fileName, sizeof fileName,
  1064.               BS_VALID) == BACKED_OUT)
  1065.                 {
  1066.                 PushBack('\b');
  1067.                 again = TRUE;
  1068.                 oChar(' ');
  1069.                 break;
  1070.  
  1071.                 }
  1072.               if (*letter == 'D') doDir   = TRUE;
  1073.               else      extDir  = TRUE;
  1074.               break;
  1075.  
  1076.               }
  1077.             else
  1078.               {
  1079.               Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1080.               abort = TRUE;
  1081.               break;
  1082.  
  1083.               }
  1084.  
  1085.             }
  1086.           else
  1087.             {
  1088.             Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  1089.             abort = TRUE;
  1090.  
  1091.             }
  1092.  
  1093.           }
  1094.         break;
  1095.         case 'I':
  1096.         if (doInviteDisplay() == BACKED_OUT)
  1097.           {
  1098.           PushBack('\b');
  1099.           again = TRUE;
  1100.           oChar(' ');
  1101.           break;
  1102.  
  1103.           }
  1104.         KillList(&RSelects);
  1105.         return  GOOD_SELECT;
  1106.         case 'P':
  1107.         srchPhrase = TRUE;
  1108.         PhraseUser = TRUE;
  1109.         break;
  1110.         case 'U':
  1111.         SrchUser = TRUE;
  1112.         PhraseUser = TRUE;
  1113.         break;
  1114.         default:
  1115.         if ((protocol = FindProtocolCode(*letter, FALSE)) == -1)
  1116.         abort = TRUE;
  1117.  
  1118.         }
  1119.       letter++;
  1120.  
  1121.       }
  1122.     while (moreYet && !abort && *letter);
  1123.  
  1124.     }
  1125.   while (again);
  1126.   KillList(&RSelects);
  1127.   KillList(&CSelects);
  1128.   if (abort) return GOOD_SELECT;
  1129.   if (status)
  1130.     {
  1131.     systat();
  1132.     return GOOD_SELECT;
  1133.  
  1134.     }
  1135.   if (ReadArchive)
  1136.     {
  1137.     #ifdef NO_DeARC_SUPPORT
  1138.     getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1139.     if (srchPhrase)
  1140.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1141.     mPrintf("\n %7s%8s%5s Name...\n ", "Crunched", "Normal", "date");
  1142.     wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1143.     #else
  1144.     if (ReadArchive == 1)
  1145.       {
  1146.       getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1147.       if (srchPhrase)
  1148.       getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1149.       if (strchr(fileName, '.') == NULL) strCat(fileName, ".arc");
  1150.       wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1151.  
  1152.       }
  1153.     else if (ReadArchive == 2)
  1154.     SendArcFiles(protocol);
  1155.     #endif
  1156.     return GOOD_SELECT;
  1157.  
  1158.     }
  1159.   if (doDir || extDir)
  1160.     {
  1161.     if (srchPhrase)
  1162.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1163.     if (!global)
  1164.     doDirectory(doDir, fileName, Opt.Phrase);
  1165.     else
  1166.       {
  1167.       CurRoom = thisRoom;
  1168.       /* should we have tableRunner() do this for us? */
  1169.       for (thisRoom = 0; outFlag == OUTOK && thisRoom < MAXROOMS;
  1170.       thisRoom++)
  1171.       if (roomTab[thisRoom].rtflags.INUSE &&
  1172.       roomTab[thisRoom].rtflags.ISDIR &&
  1173.       (roomTab[thisRoom].rtflags.DOWNLOAD || SomeSysop()) &&
  1174.       knowRoom(&logBuf, thisRoom) == KNOW_ROOM)
  1175.         {
  1176.         getRoom(thisRoom);
  1177.         mPrintf("\n (%s)\n ", roomBuf.rbname);
  1178.         doCR();   /* nice left side now */
  1179.         doDirectory(doDir, fileName, Opt.Phrase);
  1180.         if (outFlag == OUTNEXT) outFlag = OUTOK;
  1181.  
  1182.         }
  1183.       getRoom(CurRoom);
  1184.  
  1185.       }
  1186.     if (journalMessage)
  1187.       {
  1188.       if (redirect(NULL))
  1189.         {
  1190.         doDirectory(doDir, fileName, Opt.Phrase);
  1191.         undirect();
  1192.         /* fclose(upfd);
  1193.         outPut = NORMAL; */
  1194.  
  1195.         }
  1196.       journalMessage = FALSE;
  1197.  
  1198.       }
  1199.     return GOOD_SELECT;
  1200.  
  1201.     }
  1202.   if (hostFile)
  1203.     {
  1204.     if (srchPhrase)
  1205.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1206.     TranFiles(protocol, Opt.Phrase);
  1207.     FormatFlag = FALSE;
  1208.     return GOOD_SELECT;
  1209.  
  1210.     }
  1211.   if (SrchUser)
  1212.     {
  1213.     getList(UserOptAdd, "Users", NAMESIZE * 3, FALSE);
  1214.  
  1215.     }
  1216.   if (srchPhrase)
  1217.   getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1218.   if (Compressed)
  1219.     {
  1220.     if ((Compressed = GetUserCompression()) == NO_COMP)
  1221.     return GOOD_SELECT;
  1222.     doCR();
  1223.  
  1224.     }
  1225.   else Compressed = NO_COMP;
  1226.   download(whichMess, revOrder, protocol, global, Compressed);
  1227.   KillList(&Opt.Users);
  1228.   return GOOD_SELECT;
  1229.  
  1230.   }
  1231. /*
  1232. * UserOptAdd()
  1233. *
  1234. * This adds the given name to a list.
  1235. */
  1236. int UserOptAdd(char *str)
  1237.   {
  1238.   AddData(&Opt.Users, strdup(str), NULL, FALSE);
  1239.   return TRUE;
  1240.  
  1241.   }
  1242. /*
  1243. * FindUser()
  1244. *
  1245. * Is the current user @system _ domain going to match?
  1246. */
  1247. static void *FindUser(char *element, int x)
  1248. /* x is actually not used -- we use global msgBuf */
  1249.   {
  1250.   label User;
  1251.   char System[(2 * NAMESIZE) + 2];
  1252.   System[0] = 0;
  1253.   SepNameSystem(element, User, System, NULL);
  1254.   if (strLen(User) != 0 && matchString(msgBuf.mbauth, User,
  1255.   lbyte(msgBuf.mbauth)) == NULL)
  1256.     {
  1257.     if (strLen(msgBuf.mbto) == 0) return NULL;
  1258.     if (matchString(msgBuf.mbto, User, lbyte(msgBuf.mbto)) == NULL)
  1259.     return NULL;
  1260.  
  1261.     }
  1262.   if (strLen(System) != 0)
  1263.     {
  1264.     if (matchString(msgBuf.mboname, System, lbyte(msgBuf.mboname))
  1265.     == NULL &&
  1266.     matchString(msgBuf.mbdomain, System, lbyte(msgBuf.mbdomain)) == NULL)
  1267.     return NULL;
  1268.  
  1269.     }
  1270.   return element;
  1271.  
  1272.   }
  1273. /*
  1274. * OptionValidate()
  1275. *
  1276. * This is sent to showMessages.
  1277. */
  1278. char OptionValidate(int mode)
  1279.   {
  1280.   if (OptionCheck(mode))
  1281.     {
  1282.     printMessage(0);
  1283.     return Pause_Message_Check();
  1284.  
  1285.     }
  1286.   else mAbort();      /* give a chance to interrupt */
  1287.   return (char)( (mode == 1) ? TRUE : FALSE);
  1288.  
  1289.   }
  1290. /*
  1291. * OptionCheck()
  1292. *
  1293. * This function checks to see if all options fulfilled.
  1294. */
  1295. char OptionCheck(char mode)
  1296.   {
  1297.   long MsgTime;
  1298.   int  rover;
  1299.   if (mode == 1)
  1300.   return (char) (!Opt.LocalOnly && GetFirst(&Opt.Users) == NULL &&
  1301.   strLen(Opt.Phrase) == 0 && Opt.Date == -1l);
  1302.   /* else */
  1303.   /*
  1304.   * If any match failures, don't print.  printMessage(0) indicates a
  1305.   * a print with msg still on disk, while a (1) indicates message now in
  1306.   * the message buffer.
  1307.   */
  1308.   if (Opt.LocalOnly && msgBuf.mboname[0] &&
  1309.   strCmpU(msgBuf.mboname, cfg.codeBuf + cfg.nodeName) != SAMESTRING)
  1310.   return (char)FALSE;
  1311.   if (Opt.Date != -1l)
  1312.   if (ReadDate(msgBuf.mbdate, &MsgTime) != ERROR)
  1313.   if ((!revOrder && MsgTime < Opt.Date) ||
  1314.   (revOrder && MsgTime > Opt.Date))  return (char )FALSE;
  1315.   if (GetFirst(&Opt.Users) != NULL)
  1316.   if (SearchList(&Opt.Users, 0) == NULL) return NULL;
  1317.   if (strLen(Opt.Phrase) != 0)
  1318.     {
  1319.     getMsgStr(getMsgChar, msgBuf.mbtext, MAXTEXT);
  1320.     /* Kill extraneous line breaks */
  1321.     for (rover = 0; msgBuf.mbtext[rover]; rover++)
  1322.     if (msgBuf.mbtext[rover] == NEWLINE &&
  1323.     msgBuf.mbtext[rover + 1] != ' ' &&
  1324.     msgBuf.mbtext[rover + 1] != NEWLINE)
  1325.     msgBuf.mbtext[rover] = ' ';
  1326.     if (matchString(msgBuf.mbtext, Opt.Phrase, lbyte(msgBuf.mbtext))
  1327.     != NULL)
  1328.       {
  1329.       findMessage(msgBuf.mbheadSector, atol(msgBuf.mbId), TRUE);
  1330.       return (char)TRUE;
  1331.  
  1332.       }
  1333.     else return (char)FALSE;
  1334.  
  1335.     }
  1336.   return (char)TRUE;
  1337.  
  1338.   }
  1339. /*
  1340. * doDirectory()
  1341. *
  1342. * This function handles the read directory commands.
  1343. */
  1344. void doDirectory(char doDir, char *fileName, char *phrase)
  1345.   {
  1346.   #ifdef OLD_STYLE
  1347.   extern long BDSizeCount;
  1348.   int   FileCount;
  1349.   if (doDir)
  1350.     {
  1351.     FDSectCount     = 0;      /* global fDir() totals sectors in   */
  1352.     FileCount = wildCard(fDir, fileName, TRUE, phrase, TRUE);
  1353.     mPrintf("\n %d files, approximately %s sectors total\n ", FileCount,
  1354.     PrintPretty(FDSectCount, msgBuf.mbtext));
  1355.  
  1356.     }
  1357.   else
  1358.     {
  1359.     BDSizeCount = 0l;
  1360.     FileCount = wildCard(ShowVerbose, fileName, TRUE, phrase, TRUE);
  1361.     mPrintf("\n %d files, %s bytes total.\n ", FileCount,
  1362.     PrintPretty(BDSizeCount, msgBuf.mbtext));
  1363.  
  1364.     }
  1365.   #else
  1366.   int   FileCount;
  1367.   extern long FDSize;
  1368.   FDSize = 0l;
  1369.   FileCount = wildCard((doDir) ? fDir : ShowVerbose, fileName, TRUE, phrase,
  1370.   TRUE);
  1371.   mPrintf("\n %d files, ", FileCount);
  1372.   mPrintf((doDir) ? "approximately %s sectors total\n " :
  1373.   "%s bytes total.\n ",
  1374.   PrintPretty(FDSize, msgBuf.mbtext));
  1375.   #endif
  1376.   giveSpaceLeft(&roomBuf);
  1377.  
  1378.   }
  1379. #define MAX_USER_ERRORS 25
  1380. /*
  1381. * doRegular()
  1382. *
  1383. * The big fanout.
  1384. */
  1385. char doRegular(char x, char c)
  1386.   {
  1387.   static int errorCount = 0;
  1388.   char       toReturn, cc[2];
  1389.   SListBase  RegSelects =
  1390.     {
  1391.     NULL, FindSelect, NULL, NoFree, NULL
  1392.  
  1393.     };
  1394.   char *RegOpts[] =
  1395.     {
  1396.     TERM "Chat",    TERM "Door",       TERM "!", TERM "Enter",
  1397.     TERM "F\bRead", TERM "Goto",       TERM "+\bGoto",
  1398.     TERM "Read",    TERM "O\bRead",    TERM "N\bRead",
  1399.     TERM "Help",    TERM "Information",TERM "Known rooms",
  1400.     TERM "Login",   TERM "Skip",       TERM "Terminate",
  1401.     TERM "Backup",  TERM "Ungoto",     TERM "-\bBackup",
  1402.     TERM "QWK Mail",TERM "\\",         TERM ";",
  1403.     TERM "Z\bForget", TERM "?",
  1404.      " ",               " ",                ""
  1405.  
  1406.     };
  1407.   char       *legal = "CD!EFG+HIKLMNORSTBU-QZ";
  1408.   toReturn = GOOD_SELECT;
  1409.   if (loggedIn)
  1410.     {
  1411.     if (aide ||(strCmpU(logBuf.lbname,AskForNSMap(&Moderators, thisRoom))  == SAMESTRING ||
  1412.                 strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator)    == SAMESTRING))
  1413.         ExtraOption(RegOpts, TERM "Aide special fn:");
  1414.     if (!MeetDisabled)
  1415.       {
  1416.       ExtraOption(RegOpts, TERM "Meet User");
  1417.  
  1418.       }
  1419.     else ExtraOption(RegOpts, TERM "Moo!");
  1420.  
  1421.     };
  1422.    SpecialMessage("Status:User Idle");
  1423.  
  1424.   if (strchr(legal, c) != NULL) errorCount = 0;
  1425.   else        errorCount++;
  1426.   PushBack(c);  /* ugly kludge */
  1427.   if ((cc[0] = c) == 0 ||
  1428.   CmdMenuList(RegOpts, &RegSelects, NULL, cc, x, FALSE) == GOOD_SELECT)
  1429.     {
  1430.     switch (cc[0])
  1431.       {
  1432.       case 'C': toReturn = doChat(  x, '\0');     break;
  1433.       case '!':
  1434.       case 'D': toReturn = doDoor(  x);     break;
  1435.       case 'E': toReturn = doEnter( x, 'M' );     break;
  1436.       case 'F': toReturn = doRead(  x, 'F' );     break;
  1437.       case '+':
  1438.       case 'G': toReturn = doGoto(  x);     break;
  1439.       case 'H': toReturn = doHelp(  x);     break;
  1440.       case 'I': toReturn = doInfo();        break;
  1441.       case 'K': toReturn = doKnown( x);     break;
  1442.       case 'L': toReturn = doLogin( x);     break;
  1443.       case 'M': if (!MeetDisabled) toReturn = doMeet( x); break;
  1444.       case 'N': toReturn = doRead(  x, 'N' );     break;
  1445.       case 'O': toReturn = doRead(  x, 'O' );     break;
  1446.       case 'Q': toReturn = QWKmain();             break;
  1447.       case 'R': toReturn = doRead(  x, 'R' );     break;
  1448.       case 'S': toReturn = doSkip(  x);     break;
  1449.       case 'T': toReturn = doLogout(x, 'Q' );     break;
  1450.       case '-':
  1451.       case 'B': /* k2ne ism */
  1452.       case 'U': toReturn = doUngoto(x);     break;
  1453.       case '\'':
  1454.       case ';': toReturn = DoFloors();      break;
  1455.       case 0:
  1456.       pause(1);          /* To clear line noise */
  1457.       while (MIReady())   inp();   /* eat noise */
  1458.       if (newCarrier)
  1459.         {
  1460.         greeting();
  1461.         newCarrier  = FALSE;
  1462.  
  1463.         }
  1464.       if (justLostCarrier)
  1465.         {
  1466.         justLostCarrier = FALSE;
  1467.         terminate(TRUE, TRUE);
  1468.  
  1469.         }
  1470.       break;  /* irrelevant value */
  1471.       case '?':
  1472.       tutorial("mainopt.mnu", TRUE);
  1473.       if (whichIO == CONSOLE)   mPrintf("\n ^l: SysOp privileged fns\n ");
  1474.       break;
  1475.       case 'A': toReturn = doAide(x, 'E');      break;
  1476.       case 'Z': toReturn = doForget(x);     break;
  1477.       default:
  1478.       if (errorCount > MAX_USER_ERRORS)
  1479.         {
  1480.         logMessage(EVIL_SIGNAL, "", 'E');
  1481.         HangUp(TRUE);
  1482.  
  1483.         }
  1484.       toReturn=BAD_SELECT;
  1485.       break;
  1486.  
  1487.       }
  1488.  
  1489.     }
  1490.   if (toReturn == BACKED_OUT)
  1491.     {
  1492.     PushBack('\b');
  1493.     CmdMenuList(RegOpts, &RegSelects, NULL, cc, FALSE, FALSE);   /* does the BS */
  1494.  
  1495.     }
  1496.   KillList(&RegSelects);
  1497.   return  toReturn;
  1498.  
  1499.   }
  1500. /*
  1501. * doSkip()
  1502. *
  1503. * This function handles the <S>kip a room command.
  1504. */
  1505. char doSkip(char expand)
  1506.   {
  1507.   label roomName;     /* In case of ".Skip" */
  1508.   char  dispbuf[2 * NAMESIZE];
  1509.   int   rover;
  1510.   outFlag = IMPERVIOUS;
  1511.   sPrintf(dispbuf, "%s> goto ", roomTab[thisRoom].rtname);
  1512.   mPrintf("%s", dispbuf);
  1513.   if (expand)
  1514.     {
  1515.     if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  1516.       {
  1517.       for (rover = 0; rover < strLen(dispbuf); rover++)
  1518.         {
  1519.         mPrintf("\b \b");
  1520.  
  1521.         }
  1522.       return BACKED_OUT;
  1523.  
  1524.       }
  1525.  
  1526.     }
  1527.   else
  1528.   roomName[0] = '\0';
  1529.   if (roomName[0] == '?')
  1530.   tutorial("skip.hlp", TRUE);
  1531.   else
  1532.     {
  1533.     roomTab[thisRoom].rtflags.SKIP = 1;     /* Set bit */
  1534.     gotoRoom(roomName, 'S');
  1535.  
  1536.     }
  1537.   return GOOD_SELECT;
  1538.  
  1539.   }
  1540. /*
  1541. * doSysop()
  1542. *
  1543. * This function handles the sysop-only menu.  It returns FALSE to fall
  1544. * invisibly into default error msg.
  1545. */
  1546. char doSysop()
  1547.   {
  1548.   extern unsigned long S_min, S_max;  /* stack tracking variables */
  1549.   extern char *NoFileStr;
  1550.   MSG_NUMBER  temp;
  1551.   int i;
  1552.   char  systemPW[200];
  1553.  
  1554.  
  1555.   extern char *VERSION, *LCHeld, *netVersion, *SysVers;
  1556.   extern int  fixVers, majorVers;
  1557.   logBuffer   lBuf;   /* This has to be local!  Don't sub logTmp */
  1558.   MenuId  id;
  1559.   char Priv[] = "\n Privileged Functions\n ";
  1560.   char  *CtdlOpts[] =
  1561.     {
  1562.     "A(bort)          ", "B(aud rate)           ", "C(hat mode)\n",
  1563.     "D(ebug mode)     ", "E(cho)                ", "F(ile grab)\n",
  1564.     "I(nformation)    ", "M(ODEM mode)          ", "N(et Menu)\n" ,
  1565.     "O(ther Commands) ", "R(einitialize Modem)  ", "Q(debug)\n",
  1566.     "U(ser Admin)     ", "G(Special Debug)      ", "X(exit from Citadel)\n",
  1567.     #ifdef NEED_MSG_PEEKING
  1568.     "Z ",
  1569.     #endif
  1570.     #ifdef NEED_MSG_LIST
  1571.     "Y ",
  1572.     #endif
  1573.     "1 ",    " W ",    "Z\n",   ""
  1574.  
  1575.     };
  1576.   if ((!onConsole || ConsolePassword) && !remoteSysop)
  1577.     {
  1578.     if (!(onConsole && ConsolePassword && strLen(cfg.sysPassword) == 0))
  1579.       {
  1580.       if ((!aide && !onConsole) || strLen(cfg.sysPassword) == 0)
  1581.         {
  1582.         return BAD_SELECT;
  1583.  
  1584.         }
  1585.       echo  = CALLER;
  1586.       getNormStr("SYSPWD", systemPW, sizeof systemPW, NO_ECHO);
  1587.       echo  = BOTH;
  1588.       if (strCmp(systemPW, cfg.sysPassword) != 0)
  1589.       return BAD_SELECT;
  1590.       remoteSysop = TRUE;
  1591.  
  1592.       }
  1593.  
  1594.     }
  1595.   initLogBuf(&lBuf);
  1596.  
  1597.    SpecialMessage("Status:***Sysop***");
  1598.  
  1599.   if (whichIO == CONSOLE && gotCarrier())
  1600.     Output_Citadel_Message("ONEMOM", NULL, NULL, NULL);
  1601.   id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1602.   while (onLine())
  1603.     {
  1604.     outFlag = OUTOK;
  1605.     SysopMenuPrompt(id, "\n privileged fn: ");
  1606.     switch (GetSysopMenuChar(id))
  1607.       {
  1608.       case 'W':
  1609.       EventShow();  /* Debug stuff */
  1610.       break;
  1611.       case '1':
  1612.       for (i = 0; i < MSGSPERRM; i++)
  1613.         {
  1614.         if (findMessage(roomBuf.msg[i].rbmsgLoc, roomBuf.msg[i].rbmsgNo,
  1615.         TRUE))
  1616.           {
  1617.           mPrintf("(%s : %s) ", msgBuf.mbsrcId, msgBuf.mboname);
  1618.  
  1619.           }
  1620.         mPrintf("%ld: %d\n ", roomBuf.msg[i].rbmsgNo,
  1621.         roomBuf.msg[i].rbmsgLoc);
  1622.  
  1623.         }
  1624.       break;
  1625.       #ifdef NEED_MSG_LIST
  1626.       case 'Y':
  1627.       CloseSysopMenu(id);
  1628.       for (i = 0; i < MSGSPERRM; i++)
  1629.         {
  1630.         mPrintf(" Room:%-20s:%ld: %d\n ",
  1631.         roomBuf.msg[i].rbname,
  1632.         roomBuf.msg[i].rbmsgNo,
  1633.         roomBuf.msg[i].rbmsgLoc);
  1634.         if( (i%20) == 19)iChar();
  1635.  
  1636.         };
  1637.       iChar();
  1638.       id = RegisterSysopMenu("ctdlopt.mnu",CtdlOpts,Priv);
  1639.       break;
  1640.       #endif
  1641.       #ifdef NEED_MSG_PEEKING
  1642.       case 'Z':
  1643.       CloseSysopMenu(id);
  1644.       mPeek();
  1645.       iChar();
  1646.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1647.       break;
  1648.       #endif
  1649.       case 'B':
  1650.       changeBauds(id);
  1651.       break;
  1652.       case 'E':
  1653.       sPrintf(systemPW, "%sabled\n ",
  1654.       (anyEcho = !anyEcho) ? "en" : "dis");
  1655.       ScrNewUser();
  1656.       SysopInfoReport(id, systemPW);
  1657.       break;
  1658.       case 'F':
  1659.       SysopRequestString(id, "EFILEN", systemPW, 50, 0);
  1660.       if (!ingestFile(systemPW, &tempMess))
  1661.         {
  1662.         char *fn;
  1663.         fn = strdup(systemPW);
  1664.         sPrintf(systemPW, NoFileStr, fn);
  1665.         SysopError(id, systemPW);
  1666.         free(fn);
  1667.  
  1668.         }
  1669.       break;
  1670.       case 'A':
  1671.       killLogBuf(&lBuf);
  1672.       CloseSysopMenu(id);
  1673.       return GOOD_SELECT;
  1674.       case 'C':
  1675.       cfg.BoolFlags.noChat =  (cfg.BoolFlags.noChat== 1) ? 0 : 1;
  1676.       sPrintf(systemPW, "%sabled\n ",cfg.BoolFlags.noChat ? "dis" : "en" );
  1677.       ScrNewUser();
  1678.       SysopInfoReport(id, systemPW);
  1679.       break;
  1680.       case 'D':
  1681.       cfg.BoolFlags.debug =  (cfg.BoolFlags.debug == 1) ? 0 : 1;
  1682.       sPrintf(systemPW, "%sabled\n ", cfg.BoolFlags.debug ? "en" : "dis");
  1683.       SysopInfoReport(id, systemPW);
  1684.       break;
  1685.       case 'G':
  1686.       cfg.BoolFlags.tdebug =  (cfg.BoolFlags.tdebug == 1) ? 0 : 1;
  1687.       sPrintf(systemPW, "%sabled Special Debug Flag\n ", cfg.BoolFlags.tdebug ? "en" : "dis");
  1688.       SysopInfoReport(id, systemPW);
  1689.       break;
  1690.       case 'I':
  1691.       sPrintf(msgBuf.mbtext, "\n %s V%s%s\n Net version %s", VARIANT_NAME, VERSION, SysVers, netVersion);
  1692.       sPrintf(lbyte(msgBuf.mbtext), "\n Commands version %d.%d    ", majorVers, fixVers);
  1693.       sPrintf(lbyte(msgBuf.mbtext), "ctdlcnfg.sys version %d\n ", cfg.paramVers);
  1694.       sPrintf(lbyte(msgBuf.mbtext), "ARexx Port: %s\n ", &cfg.DepData.ARexxPort);
  1695.       sPrintf(lbyte(msgBuf.mbtext), "Message Base Oldest: %ld  Newest: %ld \n ",cfg.newest,cfg.oldest);
  1696.       sPrintf(lbyte(msgBuf.mbtext), "Stack Usage: Min:%lx Max:%lx Size:%lx\n ",S_min,S_max,(S_max - S_min + 1));
  1697.       if( cfg.Audit != 0)sPrintf(lbyte(msgBuf.mbtext), "You are caller number %ld\n ",Get_Call_Count());
  1698.       sPrintf(lbyte(msgBuf.mbtext), "You have %s privledges\n ",Display_Privledges());
  1699.       ActiveEvents(msgBuf.mbtext);
  1700.       SysopDisplayInfo(id, msgBuf.mbtext, " Info ");
  1701.       break;
  1702.       case 'M':
  1703.       CloseSysopMenu(id);
  1704.       if (whichIO != MODEM)
  1705.         {
  1706.         whichIO = MODEM;
  1707.         setUp(FALSE);
  1708.  
  1709.         }
  1710.       printf("Chat mode %sabled\n ",
  1711.       cfg.BoolFlags.noChat  ?  "dis"  :  "en");
  1712.       if (!gotCarrier())
  1713.         {
  1714.         EnableModem(FALSE);
  1715.         ReInitModem();
  1716.  
  1717.         }
  1718.       #ifdef NEED_VISIBLE
  1719.       if (visibleMode) mPrintf("Visible mode on\n ");
  1720.       #endif
  1721.       killLogBuf(&lBuf);
  1722.       ScrNewUser();
  1723.       startTimer(NEXT_ANYNET);      /* start up anytime net timer */
  1724.       if (gotCarrier()) mPrintf("System on-line\n ");
  1725.       return GOOD_SELECT;
  1726.       case 'O':
  1727.       CloseSysopMenu(id);
  1728.       systemCommands();
  1729.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1730.       break;
  1731.       #ifdef MAKE_AVAILABLE
  1732.       case 'S':
  1733.       changeDate();
  1734.       break;
  1735.       #endif
  1736.       #ifdef NEED_VISIBLE
  1737.       case 'V':
  1738.       mPrintf(" VisibleMode==%d\n ",  visibleMode = !visibleMode);
  1739.       break;
  1740.       #endif
  1741.       case ERROR:
  1742.       case 'X':
  1743.       if (!SysopGetYesNo(id, NULL, "CONFRM")) break;
  1744.       ExitToMsdos = TRUE;
  1745.       exitValue   = (remoteSysop && !onConsole) ? REMOTE_SYSOP_EXIT : SYSOP_EXIT;
  1746.       CloseSysopMenu(id);
  1747.       return GOOD_SELECT;
  1748.       case 'N':
  1749.       CloseSysopMenu(id);
  1750.       netStuff();
  1751.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1752.       break;
  1753.       case 'R':
  1754.       if (gotCarrier()) HangUp(TRUE);
  1755.       Reinitialize();
  1756.       break;
  1757.       case 'Q':
  1758.       temp = SysopGetNumber(id, "SETOLD", 0l, 200000l);
  1759.       if (temp != 0l) cfg.oldest = temp;
  1760.       break;
  1761.       case 'U':
  1762.       CloseSysopMenu(id);
  1763.       UserAdmin(&lBuf);
  1764.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1765.       break;
  1766.  
  1767.       }
  1768.  
  1769.     }
  1770.   killLogBuf(&lBuf);
  1771.   CloseSysopMenu(id);
  1772.   return GOOD_SELECT;
  1773.  
  1774.   }
  1775. /*
  1776. * doUngoto()
  1777. *
  1778. * This function handles the Ungoto command.
  1779. */
  1780. char doUngoto(char moreYet)
  1781.   {
  1782.   label target;
  1783.   if (!moreYet)
  1784.     {
  1785.     strCpy(target, "");
  1786.  
  1787.     }
  1788.   else
  1789.     {
  1790.     if (getNormStr("", target, NAMESIZE, BS_VALID) == BACKED_OUT)
  1791.     return BACKED_OUT;
  1792.  
  1793.     }
  1794.   retRoom(target);
  1795.   return GOOD_SELECT;
  1796.  
  1797.   }
  1798. /*
  1799. * getCommand()
  1800. *
  1801. * This function prints the menu prompt and gets command char and returns a
  1802. * char via parameter and expand flag as value -- i.e., TRUE if parameters
  1803. * follow else FALSE.
  1804. */
  1805. char getCommand(char *c, char bs)
  1806.   {
  1807.   char expand, again;
  1808.   outFlag = OUTOK;
  1809.   if (!bs)
  1810.   givePrompt();
  1811.   do
  1812.     {
  1813.     again = FALSE;
  1814.     /* bizarre cheat */
  1815.     if (!bs)
  1816.       {
  1817.       if( justLostCarrier )
  1818.         {
  1819.         *c = 0;
  1820.  
  1821.         }
  1822.       else
  1823.         {
  1824.         *c = modIn();
  1825.         *c = toUpper(*c);
  1826.  
  1827.         };
  1828.  
  1829.       }
  1830.     else *c = '.';
  1831.     expand  = ( *c == ' ' || *c == '.' || *c == ',' || *c == '/' );
  1832.     if (expand)
  1833.       {
  1834.       if (!bs) oChar(*c);
  1835.       *c = modIn();
  1836.       if ((*c = toUpper(*c)) == '\b')
  1837.         {
  1838.         mPrintf("\b \b");
  1839.         again = TRUE;
  1840.  
  1841.         }
  1842.  
  1843.       }
  1844.     /* catch a late Pause, et al, command */
  1845.     else if (*c == 'P' || *c == '\b') again = TRUE;
  1846.     else if (*c == 7)
  1847.       {
  1848.       if( CheckForSpecial(13,69))netController(0,0,NO_NETS, ANY_CALL,0);
  1849.       }
  1850.     /* else oChar(*c); -- actually, handled somewhere else! */
  1851.     bs = FALSE;
  1852.  
  1853.     }
  1854.   while (again && onLine());
  1855.   if (justLostCarrier)
  1856.     {
  1857.     justLostCarrier = FALSE;
  1858.     terminate(TRUE, TRUE);
  1859.     expand = 0;
  1860.  
  1861.     }
  1862.   return expand;
  1863.  
  1864.   }
  1865. /*
  1866. * greeting()
  1867. *
  1868. * This gives system-entry blurb etc.
  1869. */
  1870. void greeting()
  1871.   {
  1872.   extern char *VERSION, *SysVers;
  1873.   extern int logTries;
  1874.   if (loggedIn) terminate(FALSE, TRUE);
  1875.   setUp(TRUE);     pause(10);
  1876.   logTries = 1; /* put this here instead of setUp() */
  1877.   PrintBanner = TRUE; /* signal for anytime net */
  1878.   doCR();
  1879.   expert = TRUE;
  1880.   HelpIfPresent("banner.pre");
  1881.   if (!MultiBanner("banner"))
  1882.   if (!HelpIfPresent("banner.blb"))
  1883.     Output_Citadel_Message("NODETL",NULL,NULL,NULL);
  1884.   HelpIfPresent("banner.sfx");
  1885.   expert = FALSE;
  1886.   Output_Citadel_Message("VERSIN",NULL,NULL,NULL);
  1887.   Output_Citadel_Message("HELPOP",NULL,NULL,NULL);
  1888.   printf("Chat mode %sabled\n", cfg.BoolFlags.noChat ? "dis" : "en");
  1889.   printf("\n 'MODEM' mode.\n "      );
  1890.   printf("(<ESC> for CONSOLE mode.)\n "   );
  1891.   while (MIReady())
  1892.   inp();
  1893.   gotoRoom(baseRoom, 'R');
  1894.   setUp(TRUE);
  1895.   PrintBanner = FALSE;
  1896.   if (outFlag == NET_CALL)
  1897.     {
  1898.     netController(0, 0, NO_NETS, ANY_CALL, 0);   /* so we don't call out */
  1899.  
  1900.     }
  1901.   else if (outFlag == STROLL_DETECTED)
  1902.     {
  1903.     StrollIt();
  1904.  
  1905.     }
  1906.   outFlag = OUTOK;
  1907.  
  1908.   }
  1909. /*
  1910. * main()
  1911. *
  1912. * This is the main manager.
  1913. */
  1914. void main(int argc, char **argv)
  1915.   {
  1916.   extern char logNetResults, netDebug, DisVandals;
  1917.   extern char netdebuglog;
  1918.   extern char VortexHandle, BpsSet, *kip, ItlWxmodem, Zmodem, NoConsoleBanner;
  1919.   extern int  ParanoiaLimit, LD_Delay;
  1920.   extern long LowFree;
  1921.   char c, x, errMsg;
  1922.   int  CmdResult = GOOD_SELECT;
  1923.   /*
  1924.    initialize global data items
  1925.   */
  1926.   results_debug      = FALSE;    /* debug modem results codes */
  1927.   results_cid        = FALSE;    /* collect caller ID info if present */
  1928.   cfg.weAre          = CITADEL;
  1929.   errMsg             = FALSE;
  1930.   SysVers            = SYSDEP_NAME ;
  1931.   SystemPort         = 0;
  1932.   ExitToMsdos        = FALSE;     /* True when time to bring system down  */
  1933.   exitValue          = CRASH_EXIT;
  1934.   iconify_window     = FALSE;    /* not iconified so printf uses
  1935.                                     crash.sys for output in startup     */
  1936.   R_W_ANY     = "rb+";
  1937.   READ_ANY    = "rb";
  1938.   READ_TEXT   = "ra";
  1939.   APPEND_TEXT = "aa";
  1940.   APPEND_ANY  = "ab";
  1941.   A_C_TEXT    = "ab";
  1942.   WRITE_TEXT  = "wa";
  1943.   W_R_ANY     = "wb+";
  1944.   WRITE_ANY   = "wb";
  1945.  
  1946.   while (argc >= 2)
  1947.     {
  1948.     argc--;
  1949.     if (strCmpU(argv[argc], "+netlog") == SAMESTRING)
  1950.       {
  1951.       logNetResults = TRUE;
  1952.       }
  1953.     else if (strncmp(argv[argc], "+results", 4) == SAMESTRING)
  1954.       {
  1955.       results_debug = TRUE;
  1956.       }
  1957.     else if (strncmp(argv[argc], "+cid", 4) == SAMESTRING)
  1958.       {
  1959.       results_cid   = TRUE;
  1960.       }
  1961.     else if (strncmp(argv[argc], "kip=", 4) == SAMESTRING)
  1962.       {
  1963.       kip = argv[argc] + 4;
  1964.  
  1965.       }
  1966.     else if (strncmp(argv[argc], "lowfree=", 8) == SAMESTRING)
  1967.       {
  1968.       LowFree = atoi(argv[argc] + 8);
  1969.  
  1970.       }
  1971.     else if (strncmp(argv[argc], "lddelay=", 8) == SAMESTRING)
  1972.       {
  1973.       LD_Delay = atoi(argv[argc] + 8);
  1974.  
  1975.       }
  1976.     else if (strncmp(argv[argc], "paranoia=", 9) == SAMESTRING)
  1977.       {
  1978.       if ((ParanoiaLimit = atoi(argv[argc] + 9)) < 1)
  1979.       ParanoiaLimit = 10000;
  1980.  
  1981.       }
  1982.     else if (strncmp(argv[argc], "bps=", 4) == SAMESTRING)
  1983.       {
  1984.       BpsSet = TRUE;
  1985.       ReadBps(argv[argc]);
  1986.  
  1987.       }
  1988.     else if (strCmpU(argv[argc], "+netdebug") == SAMESTRING)
  1989.       {
  1990.       netDebug = TRUE;
  1991.  
  1992.       }
  1993.     else if (strCmpU(argv[argc], "+netdebuglog") == SAMESTRING)
  1994.       {
  1995.       netdebuglog = TRUE;
  1996.  
  1997.       }
  1998.     else if (strCmpU(argv[argc], "+nochat") == SAMESTRING)
  1999.       {
  2000.       NoChatAtAll = TRUE;
  2001.  
  2002.       }
  2003.     else if (strCmpU(argv[argc], "+nomeet") == SAMESTRING)
  2004.       {
  2005.       MeetDisabled = TRUE;
  2006.  
  2007.       }
  2008.     else if (strCmpU(argv[argc], "+noecho") == SAMESTRING)
  2009.       {
  2010.       anyEcho = FALSE;
  2011.  
  2012.       }
  2013.     else if (strCmpU(argv[argc], "+wx") == SAMESTRING)
  2014.       {
  2015.       #ifdef WXMODEM_AVAILABLE
  2016.       ItlWxmodem = TRUE;
  2017.       #endif
  2018.  
  2019.       }
  2020.     else if (strCmpU(argv[argc], "+vortex") == SAMESTRING)
  2021.       {
  2022.       VortexHandle = TRUE;
  2023.  
  2024.       }
  2025.     else if (strCmpU(argv[argc], "-vortex") == SAMESTRING)
  2026.       {
  2027.       VortexHandle = FALSE;
  2028.  
  2029.       }
  2030.     else if (strCmpU(argv[argc], "+vandaloff") == SAMESTRING)
  2031.       {
  2032.       DisVandals = TRUE;
  2033.  
  2034.       }
  2035.     else if (strCmpU(argv[argc], "+conpwd") == SAMESTRING)
  2036.       {
  2037.       ConsolePassword = TRUE;
  2038.  
  2039.       }
  2040.     else if (strCmpU(argv[argc], "+noconban") == SAMESTRING)
  2041.       {
  2042.       NoConsoleBanner = TRUE;
  2043.  
  2044.       }
  2045.     else if (strncmp(argv[argc], "zmodem=", 7) == SAMESTRING)
  2046.       {
  2047.       Zmodem = argv[argc][7];
  2048.  
  2049.       }
  2050.     else
  2051.       {
  2052.       printf("Invalid  argument: %s\n", argv[argc]);
  2053.       errMsg = TRUE;
  2054.  
  2055.       }
  2056.  
  2057.     }
  2058.   if (initCitadel())
  2059.     {
  2060.     greeting();
  2061.     logMessage(FIRST_IN, "", FALSE);
  2062.  
  2063.     }
  2064.   startTimer(NEXT_ANYNET);      /* start anytime net timer */
  2065.   if (errMsg)
  2066.     {
  2067.     sPrintf(msgBuf.mbtext, "System brought up from apparent crash.");
  2068.     aideMessage(NULL,FALSE);
  2069.  
  2070.     }
  2071.   while (!ExitToMsdos)
  2072.     {
  2073.     x       = getCommand(&c, (CmdResult == BACKED_OUT));
  2074.     outFlag = OUTOK;
  2075.     CmdResult = (c==CNTRLl)  ?  doSysop() : doRegular(x, c);
  2076.     if (CmdResult == BAD_SELECT)
  2077.       {
  2078.       Output_Citadel_Message("HLPMNU",NULL,NULL,NULL);
  2079.       }
  2080.  
  2081.     }
  2082.   if (loggedIn)
  2083.   terminate( /* hangUp == */ exitValue == DOOR_EXIT ? FALSE : TRUE, TRUE);
  2084.   logMessage(exitValue != DOOR_EXIT ? LAST_OUT : DOOR_OUT , "", FALSE);
  2085.   writeSysTab();
  2086.   if (onConsole) EnableModem(FALSE);  /* just in case... */
  2087.   if (exitValue != DOOR_EXIT && !cfg.BoolFlags.IsDoor) DisableModem(TRUE);
  2088.   ModemShutdown(((exitValue == DOOR_EXIT || cfg.BoolFlags.IsDoor) && !onConsole) ? FALSE : TRUE);
  2089.   systemShutdown(0);
  2090.   exit(exitValue);
  2091.  
  2092.   }
  2093. /*
  2094. * UserAdmin()
  2095. *
  2096. * This function handles the user administration menu.
  2097. */
  2098. void UserAdmin(logBuffer *lBuf)
  2099.   {
  2100.   extern SListBase MailForward;
  2101.   int      logNo, ltabSlot, result;
  2102.   SYS_FILE killHeld;
  2103.   label    who;
  2104.   MenuId   id;
  2105.   char User_Prompt[] = "\nUser Administration\n ";
  2106.   char     *UserOpts[] =
  2107.     {
  2108.     "A(dd new user)     ", "D(oor privs)  ", "E(ndless User)\n",
  2109.     "F(ile privs)       ", "K(ill user)   ", "N(et privs)\n",
  2110.     "P(rivileges-aide)  ", "T(wit)        ", "X(eXit)\n",
  2111.     ""
  2112.  
  2113.     };
  2114.   id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2115.   while (onLine())
  2116.     {
  2117.     outFlag = OUTOK;
  2118.     SysopMenuPrompt(id, "\n user admin fn: ");
  2119.     switch (GetSysopMenuChar(id))
  2120.       {
  2121.       case ERROR:
  2122.       case 'X': CloseSysopMenu(id); return ;
  2123.       case 'E': /* permanent account administration */
  2124.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2125.       logNo == cfg.MAXLOGTAB) break;
  2126.       Output_Citadel_Message((lBuf->lbflags.PERMANENT ? "NPERMA" : "PERMAC")
  2127.                             ,(long)lBuf->lbname,NULL,NULL);
  2128.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2129.       lBuf->lbflags.PERMANENT = !lBuf->lbflags.PERMANENT;
  2130.       putLog(lBuf, logNo);
  2131.       /* find position in logTab[] and update that, too */
  2132.       if ((ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE)) != ERROR)
  2133.       logTab[ltabSlot].ltpermanent = lBuf->lbflags.PERMANENT;
  2134.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2135.       logBuf.lbflags.PERMANENT = lBuf->lbflags.PERMANENT;
  2136.       break;
  2137.       case 'T':
  2138.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2139.       logNo == cfg.MAXLOGTAB) break;
  2140.  
  2141.       Output_Citadel_Message((lBuf->lbflags.TWIT ? "TWITST" : "TWITNT")
  2142.                             ,(long)lBuf->lbname,NULL,NULL);
  2143.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2144.  
  2145.       lBuf->lbflags.TWIT = !lBuf->lbflags.TWIT;
  2146.  
  2147.       putLog(lBuf, logNo);
  2148.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2149.       logBuf.lbflags.TWIT = lBuf->lbflags.TWIT;
  2150.       break;
  2151.       case 'F':
  2152.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2153.       if (logNo == cfg.MAXLOGTAB)
  2154.         {
  2155.         result = DoAllQuestion("GVFLPR","TAFLPR");
  2156.         if (result == ERROR) break;
  2157.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2158.           {
  2159.           getLog(lBuf, logNo);
  2160.           if (!onConsole) mPrintf(".");
  2161.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DL_PRIVS != result)
  2162.             {
  2163.             lBuf->lbflags.DL_PRIVS = result;
  2164.             putLog(lBuf, logNo);
  2165.  
  2166.             }
  2167.  
  2168.           }
  2169.         break;
  2170.  
  2171.         }
  2172.       Output_Citadel_Message((lBuf->lbflags.DL_PRIVS ? "NFLPRI" : "FILPRI")
  2173.                             ,(long)lBuf->lbname,NULL,NULL);
  2174.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2175.  
  2176.       lBuf->lbflags.DL_PRIVS = !lBuf->lbflags.DL_PRIVS;
  2177.       putLog(lBuf, logNo);
  2178.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2179.       logBuf.lbflags.DL_PRIVS = lBuf->lbflags.DL_PRIVS;
  2180.       break;
  2181.       case 'K':
  2182.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2183.       logNo == cfg.MAXLOGTAB) break;
  2184.       Output_Citadel_Message( "KILLTH",(long)lBuf->lbname,lBuf->credit,NULL);
  2185.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2186.       ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE);
  2187.       lBuf->lbname[0] = '\0';
  2188.       lBuf->lbpw[0  ] = '\0';
  2189.       lBuf->lbflags.L_INUSE = FALSE;
  2190.       putLog(lBuf, logNo);
  2191.       logTab[ltabSlot].ltpwhash       = 0;
  2192.       logTab[ltabSlot].ltnmhash       = 0;
  2193.       if (cfg.BoolFlags.HoldOnLost)
  2194.         {
  2195.         sPrintf(msgBuf.mbtext, LCHeld, logNo);
  2196.         makeSysName(killHeld, msgBuf.mbtext, &cfg.holdArea);
  2197.         unlink(killHeld);
  2198.  
  2199.         }
  2200.       KillData(&MailForward, who);
  2201.       UpdateForwarding();
  2202.       break;
  2203.       case 'P':
  2204.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2205.       logNo == cfg.MAXLOGTAB) break;
  2206.       if (lBuf->lbflags.AIDE == 1)
  2207.         {
  2208.         lBuf->lbflags.AIDE = 0;
  2209.         lBuf->lbgen[AIDEROOM] = ((roomTab[AIDEROOM].rtgen-1) % MAXGEN)
  2210.         << GENSHIFT;
  2211.  
  2212.         }
  2213.       else
  2214.         {
  2215.         lBuf->lbflags.AIDE = 1;
  2216.         lBuf->lbgen[AIDEROOM] = roomTab[AIDEROOM].rtgen << GENSHIFT;
  2217.         lBuf->lbgen[AIDEROOM] += MAXVISIT-1;
  2218.  
  2219.         }
  2220.       Output_Citadel_Message((lBuf->lbflags.AIDE ? "AIDPRI" : "NADPRI" )
  2221.                             ,(long)lBuf->lbname,NULL,NULL);
  2222.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2223.       putLog(lBuf, logNo);
  2224.       /* see if it is us: */
  2225.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2226.         {
  2227.         aide = (lBuf->lbflags.AIDE == 1) ? TRUE : FALSE;
  2228.         logBuf.lbgen[AIDEROOM] = lBuf->lbgen[AIDEROOM];
  2229.  
  2230.         }
  2231.       break;
  2232.       case 'D':
  2233.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2234.       if (logNo == cfg.MAXLOGTAB)
  2235.         {
  2236.         result = DoAllQuestion("GVDRPR","TADRPR");
  2237.         if (result == ERROR) break;
  2238.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2239.           {
  2240.           getLog(lBuf, logNo);
  2241.           if (!onConsole) mPrintf(".");
  2242.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DOOR_PRIVS != result)
  2243.             {
  2244.             lBuf->lbflags.DOOR_PRIVS = result;
  2245.             putLog(lBuf, logNo);
  2246.  
  2247.             }
  2248.  
  2249.           }
  2250.         break;
  2251.  
  2252.         }
  2253.       lBuf->lbflags.DOOR_PRIVS  = (lBuf->lbflags.DOOR_PRIVS == 1) ? 0 : 1;
  2254.       Output_Citadel_Message((lBuf->lbflags.DOOR_PRIVS ? "DORPRI" : "NDRPRI")
  2255.                             ,(long)lBuf->lbname,NULL,NULL);
  2256.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2257.  
  2258.       putLog(lBuf, logNo);
  2259.       /* see if it is us: */
  2260.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2261.         {
  2262.         DoorPriv = lBuf->lbflags.DOOR_PRIVS;
  2263.  
  2264.         }
  2265.       break;
  2266.       case 'N':
  2267.       NetPrivs(who);
  2268.       break;
  2269.       case 'A':
  2270.       CloseSysopMenu(id);
  2271.       newUser(&logTmp);
  2272.       id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2273.       break;
  2274.  
  2275.       }
  2276.  
  2277.     }
  2278.  
  2279.   }
  2280.